package com.carleasoft.mps.cms.business.train.service.Impl;

import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carleasoft.mps.cms.business.train.bean.entity.*;
import com.carleasoft.mps.cms.business.train.bean.po.*;
import com.carleasoft.mps.cms.business.train.bean.vo.*;
import com.carleasoft.mps.cms.business.train.constants.ExceptionTrainEnum;
import com.carleasoft.mps.cms.business.train.dao.TrainExamMapper;
import com.carleasoft.mps.cms.business.train.dao.TrainPlanMapper;
import com.carleasoft.mps.cms.business.train.service.*;
import com.carleasoft.mps.cms.utils.ObjectSelfUtil;
import com.carleasoft.mps.core.exceptions.BusinessException;
import com.carleasoft.mps.core.user.ThreadUserContext;
import com.carleasoft.mps.core.user.UserCacheData;
import com.carleasoft.mps.core.utils.IBeanUtil;
import com.carleasoft.mps.data.mybatisplus.page.PageBase;
import com.carleasoft.mps.excel.utils.ConvertTemplatePath;
import com.carleasoft.mps.excel.utils.ExcelUtils;
import org.apache.poi.ss.formula.functions.T;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 考核主表 服务实现类
 * </p>
 *
 * @author fan
 * @since 2023-05-17
 */
@Service
public class TrainExamServiceImpl extends ServiceImpl<TrainExamMapper, TrainExam> implements TrainExamService {

    @Autowired
    private TrainScoreService trainScoreService;
    @Autowired
    private TrainPlanMapper trainPlanMapper;
    @Autowired
    private TrainExamContentService trainExamContentService;
    @Autowired
    private TrainScoreContentService trainScoreContentService;
    @Autowired
    private TrainContentService trainContentService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(TrainExamAddOrEditPo trainExamAddOrEditPo) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        TrainExam trainExam = new TrainExam();
        BeanUtils.copyProperties(trainExamAddOrEditPo, trainExam);
        String code = UUID.randomUUID().toString().replaceAll("-", "");
        trainExam.setExamCode(code);
        trainExam.setStatus(1);
        trainExam.setLevelType(1);
        trainExam.setCreatePersonCode(user.getUserCode());
        trainExam.setCreatePersonName(user.getUserName());
        trainExam.setCreateTime(LocalDateTime.now());
        trainExam.setUpdatePersonCode(user.getUserCode());
        trainExam.setUpdatePersonName(user.getUserName());
        trainExam.setUpdateTime(LocalDateTime.now());
        if (trainExamAddOrEditPo.getResourceType() == 2) {
            String string = JSONObject.toJSONString(trainExamAddOrEditPo.getTargetItem());
            trainExam.setTargetItem(string);
        }
        //保存考核内容
        List<TrainExamContent> trainExamContentList = trainExamAddOrEditPo.getTrainExamContentList();
        if (!trainExamContentList.isEmpty()) {
            trainExamContentList.stream().forEach(a -> {
                TrainContent trainContentServiceOne = trainContentService.getOne(Wrappers.<TrainContent>lambdaQuery()
                        .eq(TrainContent::getBusinessCode, a.getBusinessCode()));
                a.setContent(trainContentServiceOne.getContent());
                a.setExamProject(trainContentServiceOne.getExamProject());
                a.setStandard(trainContentServiceOne.getStandard());
                a.setId(null);
                a.setExamCode(code);
            });
            trainExamContentService.saveBatch(trainExamContentList);
        }
        List<UserAndDeptMsgVo> userByDeptCodes = new ArrayList<>();
        List<TargetItemPo> targetItem = trainExamAddOrEditPo.getTargetItem();
        List<String> userCodes = new ArrayList<>();
        if (trainExamAddOrEditPo.getResourceType() == 2) {
            List<String> deptList = targetItem.stream().map(TargetItemPo::getCode).collect(Collectors.toList());
            List<String> allDeptCodesByCodeList = trainScoreService.getAllDeptCodesByCodeList(deptList);
            if (allDeptCodesByCodeList != null && allDeptCodesByCodeList.size() > 0) {
                List<UserAndDeptMsgVo> byDeptCodes = trainScoreService.getUserByDeptCodes(allDeptCodesByCodeList);
                for (UserAndDeptMsgVo byDeptCode : byDeptCodes) {
                    if (!userCodes.contains(byDeptCode.getUserCode())){
                        userByDeptCodes.add(byDeptCode);
                        userCodes.add(byDeptCode.getUserCode());
                    }
                }

            }
        } else {
            targetItem.forEach(i -> {
                if (!userCodes.contains(i.getCode())){
                    UserAndDeptMsgVo userAndDeptMsgVo = new UserAndDeptMsgVo();
                    userAndDeptMsgVo.setUserCode(i.getCode());
                    userAndDeptMsgVo.setUserName(i.getName());
                    userAndDeptMsgVo.setDeptCode(i.getDeptCode());
                    userByDeptCodes.add(userAndDeptMsgVo);
                    userCodes.add(i.getCode());
                }
            });
        }
        List<TrainScore> trainScoreList = new LinkedList<>();
        List<TrainScoreContent> trainScoreContentList = new LinkedList<>();
        if (userByDeptCodes.size() > 0) {
            userByDeptCodes.forEach(a -> {
                if (a.getUserCode()!=null){
                    TrainScore trainScore = new TrainScore();
                    String scoreCode = UUID.randomUUID().toString().replaceAll("-", "");
                    trainScore.setScoreCode(scoreCode);
                    trainScore.setCreatePersonCode(user.getUserCode());
                    trainScore.setCreatePersonName(user.getUserName());
                    trainScore.setCreateTime(LocalDateTime.now());
                    trainScore.setUpdatePersonCode(user.getUserCode());
                    trainScore.setUpdatePersonName(user.getUserName());
                    trainScore.setUpdateTime(LocalDateTime.now());
                    trainScore.setUserCode(a.getUserCode());
                    trainScore.setUserName(a.getUserName());
                    trainScore.setPart(a.getDeptCode());
                    trainScore.setExamCode(code);
                    trainScoreList.add(trainScore);
                    if (trainExamContentList.size() > 0) {
                        trainExamContentList.stream().forEach(b -> {
                            TrainScoreContent trainScoreContent = new TrainScoreContent();
                            BeanUtils.copyProperties(b, trainScoreContent);
                            trainScoreContent.setScoreCode(scoreCode);
                            trainScoreContent.setBusinessCode(UUID.randomUUID().toString().replaceAll("-", ""));
                            trainScoreContentList.add(trainScoreContent);
                        });
                    }
                }

            });
        }
        if (trainScoreList.size() > 0) {
            trainScoreService.saveBatch(trainScoreList);
        }
        if (trainScoreContentList.size() > 0) {
            trainScoreContentService.saveBatch(trainScoreContentList);//保存每个人的每项成绩信息
        }
        return this.save(trainExam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean edit(TrainExamAddOrEditPo trainExamAddOrEditPo) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        IBeanUtil.paramVerify(trainExamAddOrEditPo, "examCode");
        boolean isOk = false;
        isOk = this.remove(Wrappers.<TrainExam>lambdaQuery()
                .eq(TrainExam::getExamCode, trainExamAddOrEditPo.getExamCode()));
        List<TrainExamContent> trainExamContents = trainExamContentService.list(Wrappers.<TrainExamContent>lambdaQuery()
                .eq(TrainExamContent::getExamCode, trainExamAddOrEditPo.getExamCode()));
        List<String> codes = trainExamContents.stream().map(TrainExamContent::getBusinessCode).collect(Collectors.toList());
        isOk = trainExamContentService.remove(Wrappers.<TrainExamContent>lambdaQuery()
                .in(TrainExamContent::getBusinessCode, codes));
        List<TrainScore> trainScores = trainScoreService.list(Wrappers.<TrainScore>lambdaQuery()
                .eq(TrainScore::getExamCode, trainExamAddOrEditPo.getExamCode()));
        List<String> scoreCodes = trainScores.stream().map(TrainScore::getScoreCode).collect(Collectors.toList());
        isOk = trainScoreService.remove(Wrappers.<TrainScore>lambdaQuery()
                .in(TrainScore::getScoreCode, scoreCodes));
        List<TrainScoreContent> trainScoreContents = trainScoreContentService.list(Wrappers.<TrainScoreContent>lambdaQuery()
                .in(TrainScoreContent::getScoreCode, scoreCodes)
                .eq(TrainScoreContent::getExamCode, trainExamAddOrEditPo.getExamCode()));
        List<String> bisCodes = trainScoreContents.stream().map(TrainScoreContent::getBusinessCode).collect(Collectors.toList());
        isOk = trainScoreContentService.remove(Wrappers.<TrainScoreContent>lambdaQuery()
                .in(TrainScoreContent::getBusinessCode, bisCodes));
        isOk = this.add(trainExamAddOrEditPo);
        return isOk;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(TrainExam trainExam) {
        IBeanUtil.paramVerify(trainExam, "examCode");
        LambdaQueryWrapper<TrainExam> eq = Wrappers.lambdaQuery(TrainExam.class).eq(TrainExam::getExamCode, trainExam.getExamCode());
        trainExamContentService.remove(new QueryWrapper<TrainExamContent>().eq("EXAM_CODE", trainExam.getExamCode()));
        trainScoreService.remove(new QueryWrapper<TrainScore>().eq("EXAM_CODE", trainExam.getExamCode()));
        trainScoreContentService.remove(new QueryWrapper<TrainScoreContent>().eq("EXAM_CODE", trainExam.getExamCode()));
        return this.remove(eq);
    }

    @Override
    public Page<TrainExamVo> pageQuery(TrainExamPageQueryPo trainExamPageQueryPo) {
        Page page = new Page(trainExamPageQueryPo.getCurrent(), trainExamPageQueryPo.getSize());
        Page<TrainExamVo> trainExamVoPage = this.baseMapper.pageQuery(page, trainExamPageQueryPo);
        return trainExamVoPage;
    }

    @Override
    public TrainExamAddOrEditPo detail(TrainExam trainExam) {
        TrainExamAddOrEditPo trainExamDetailVo = new TrainExamAddOrEditPo();
        IBeanUtil.paramVerify(trainExam, "examCode");
        LambdaQueryWrapper<TrainExam> eq = Wrappers.lambdaQuery(TrainExam.class).eq(TrainExam::getExamCode, trainExam.getExamCode());
        TrainExam one = this.getOne(eq);
//        List<DeptVo> dept = trainPlanMapper.getDept();
//        Map<String, String> deptMap = dept.stream().collect(Collectors.toMap(DeptVo::getDeptCode, DeptVo::getDeptName, (k1, k2) -> k1));
        if (one != null) {
            BeanUtils.copyProperties(one, trainExamDetailVo);
            trainExamDetailVo.setResourceType(one.getResourceType());
            TrainPlan trainPlan = trainPlanMapper.selectOne(new QueryWrapper<TrainPlan>().eq("PLAN_CODE", one.getPlanCode()));
            if (trainPlan != null) {
                trainExamDetailVo.setPlanName(trainPlan.getPlanName());
            }
            //查询考核内容
            trainExamDetailVo.setTrainExamContentList(trainExamContentService.list(new QueryWrapper<TrainExamContent>().eq("EXAM_CODE", trainExam.getExamCode())));
            trainContentService.getOne(Wrappers.<TrainContent>lambdaQuery().eq(TrainContent::getBusinessCode, one.getContent()));
            if (one.getResourceType() == 2) {
                List<TargetItemPo> targetItemPos = JSONArray.parseArray(one.getTargetItem(), TargetItemPo.class);
                Set<String> deptCodes = targetItemPos.stream().map(TargetItemPo::getCode).collect(Collectors.toSet());
                List<DeptInfoVos> deptInfoVos = this.getBaseMapper().dept(deptCodes);
                Map<String, DeptInfoVos> map = deptInfoVos.stream().collect(Collectors.toMap(DeptInfoVos::getDeptCode, Function.identity()));
                for (TargetItemPo targetItemPo : targetItemPos) {
                    DeptInfoVos infoVos = map.get(targetItemPo.getCode());
                    targetItemPo.setName(infoVos.getDeptName());
                }
                trainExamDetailVo.setTargetItem(targetItemPos);
            } else {
                List<TrainScore> trainScores = trainScoreService.list(Wrappers.<TrainScore>lambdaQuery().eq(TrainScore::getExamCode, one.getExamCode()));
                List<TargetItemPo> targetItemPoList = new ArrayList<>();
                for (TrainScore trainScore : trainScores) {
                    TargetItemPo targetItemPo = new TargetItemPo();
                    targetItemPo.setCode(trainScore.getUserCode());
                    targetItemPo.setName(trainScore.getUserName());
                    targetItemPoList.add(targetItemPo);
                }
                trainExamDetailVo.setTargetItem(targetItemPoList);
            }

        }
        return trainExamDetailVo;
    }

    @Override
    public Page<TrainScoreVo> registerPageQuery(RegisterPageQuery registerPageQuery) {
        Page page = new Page(registerPageQuery.getCurrent(), registerPageQuery.getSize());
        List<String> parts = registerPageQuery.getParts();
        if (parts != null && parts.size() > 0) {
            List<String> allDeptCodesByCodeList = trainScoreService.getAllDeptCodesByCodeList(parts);
            registerPageQuery.setParts(allDeptCodesByCodeList);
        }
        return trainScoreService.registerPageQuery(page, registerPageQuery);
    }

    @Override
    public TrainScoreDetailVo registerDetail(TrainScore trainScore) {
        IBeanUtil.paramVerify(trainScore, "scoreCode");
        TrainScoreDetailVo trainScoreDetailVo = trainScoreService.registerDetail(trainScore.getScoreCode());
        if (trainScoreDetailVo != null && trainScoreDetailVo.getScoreCode() != null) {
            List<TrainScoreContent> trainScoreContents = trainScoreContentService.list(Wrappers.lambdaQuery(TrainScoreContent.class).eq(TrainScoreContent::getScoreCode, trainScoreDetailVo.getScoreCode()));
            List<TrainExamContent> trainExamContents = new ArrayList<>();
            for (TrainScoreContent trainScoreContent : trainScoreContents) {
                trainExamContents.add(BeanUtil.copyProperties(trainScoreContent, TrainExamContent.class));
            }
            trainScoreDetailVo.setTrainExamContent(trainExamContents);
        }
        return trainScoreDetailVo;
    }

    @Override
    @Transactional
    public boolean registerAddOne(TrainScorePo trainScorePo) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        TrainScore trainScore = new TrainScore();
        BeanUtils.copyProperties(trainScorePo, trainScore);
//        trainScore.setScoreCode(UUID.randomUUID().toString().replaceAll("-",""));
//        trainScore.setCreateTime(LocalDateTime.now());
//        trainScore.setCreatePersonCode(user.getUserCode());
//        trainScore.setCreatePersonName(user.getUserName());
        trainScore.setUpdateTime(LocalDateTime.now());
        trainScore.setUpdatePersonCode(user.getUserCode());
        trainScore.setUpdatePersonName(user.getUserName());
        //更新评分项
        List<TrainScoreContent> trainScoreContentList = trainScorePo.getTrainExamContent();
//        List<TrainScoreContent> collect = trainScoreContentList.stream().filter(a -> {
//            return StringUtils.isNotBlank(a.getBusinessCode());
//        }).collect(Collectors.toList());
        List<TrainScoreContent> collect = trainScoreContentList.stream().filter(i -> i.getBusinessCode() != null).collect(Collectors.toList());
        List<TrainScoreContent> collect1 = trainScoreContentList.stream().filter(a -> {
            return StringUtils.isBlank(a.getBusinessCode());
        }).collect(Collectors.toList());
        if (collect.size() > 0) {
            trainScoreContentService.updateBatchById(collect);
        }
        if (collect1.size() > 0) {
            collect1.stream().forEach(a -> {
                a.setScoreCode(trainScorePo.getScoreCode());
                a.setExamCode(trainScorePo.getExamCode());
                a.setBusinessCode(UUID.randomUUID().toString().replaceAll("-", ""));
            });
            trainScoreContentService.saveBatch(collect1);
        }
        LambdaQueryWrapper<TrainScore> eq = Wrappers.lambdaQuery(TrainScore.class).eq(TrainScore::getScoreCode, trainScorePo.getScoreCode());
        trainScoreService.update(trainScore, eq);
//        //查看是否登记完成
//        int count = trainScoreService.count(new QueryWrapper<TrainScore>().eq("EXAM_CODE", trainScorePo.getExamCode()).isNull("SCORE"));
//        if (count<=0){
//            this.update(new UpdateWrapper<TrainExam>().set("STATUS",2).eq("EXAM_CODE",trainScorePo.getExamCode()));
//        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean registerImport(MultipartFile file, String examCode) {
        boolean isOk = false;
        List<TrainExamScorePo> trainScoreList = this.parseCopy(file);
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        List<TrainScore> trainScores = trainScoreService.list(Wrappers.<TrainScore>lambdaQuery()
                .eq(TrainScore::getExamCode, examCode));
        Set<String> deptNames = trainScoreList.stream().map(TrainExamScorePo::getPartName).collect(Collectors.toSet());
        List<DeptInfoVos> deptInfoVos = this.getBaseMapper().deptInfo(deptNames);
        Map<String, DeptInfoVos> map = deptInfoVos.stream().collect(Collectors.toMap(DeptInfoVos::getDeptName, Function.identity()));
        for (TrainScore trainScore : trainScores) {
            for (TrainExamScorePo trainExamScorePo : trainScoreList) {
                DeptInfoVos infoVos = map.get(trainExamScorePo.getPartName());
                if (trainExamScorePo.getUserName().equals(trainScore.getUserName()) && infoVos.getDeptCode().equals(trainScore.getPart())) {
                    trainExamScorePo.setExamCode(examCode);
                    trainExamScorePo.setScoreCode(trainScore.getScoreCode());
                    if (StrUtil.isNotBlank(trainExamScorePo.getScore())) {
                        trainScore.setScore(trainExamScorePo.getScore());
                    }
                }
            }
        }
        isOk = trainScoreService.updateBatchById(trainScores);
        List<String> scoreCodes = trainScores.stream().map(TrainScore::getScoreCode).collect(Collectors.toList());
        List<TrainScoreContent> trainScoreContents = trainScoreContentService.list(Wrappers.<TrainScoreContent>lambdaQuery()
                .in(TrainScoreContent::getScoreCode, scoreCodes)
                .eq(TrainScoreContent::getExamCode, examCode));
        for (TrainScoreContent trainScoreContent : trainScoreContents) {
            for (TrainExamScorePo trainExamScorePo : trainScoreList) {
                if (trainScoreContent.getScoreCode().equals(trainExamScorePo.getScoreCode()) && trainScoreContent.getExamCode().equals(trainExamScorePo.getExamCode())) {
                    List<Map<String, Object>> contentMap = trainExamScorePo.getContentMap();
                    String score = trainScoreContent.getExamProject() + "得分";
                    String scoRecord = trainScoreContent.getExamProject() + "评分";
                    for (Map<String, Object> stringObjectMap : contentMap) {
                        if (stringObjectMap.containsKey(score)) {
                            String o = stringObjectMap.get(score).toString();
                            trainScoreContent.setScoRecord((o));
                        }
                        if (stringObjectMap.containsKey(scoRecord)) {
                            trainScoreContent.setScore(stringObjectMap.get(scoRecord).toString());
                        }
                    }
                }
            }
            isOk = trainScoreContentService.updateBatchById(trainScoreContents);
        }
        return isOk;
    }

    @Override
    public boolean registerDownload(HttpServletResponse response) {
        Map<String, Object> map = new HashMap<>();
        String path = "\\templates\\trainScoreTemplate.xls";
        TemplateExportParams templatePath = new TemplateExportParams(ConvertTemplatePath.convertTemplatePath(path));
        try {
            ExcelUtils.exportExcel(templatePath, map, "成绩导入模板", response);
        } catch (IOException e) {
            throw new BusinessException(ExceptionTrainEnum.TEMP_ERROR);
        }
        return true;
    }

    @Override
    public List<TrainScore> registerParse(MultipartFile file) {
        List<TrainScore> returnList = new LinkedList<>();
        if (file.isEmpty()) {
            throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
        }
        List<TrainScoreExcelMappingEntity> fl = new ArrayList<>();
        try {
            fl = ExcelUtils.importExcel(file, TrainScoreExcelMappingEntity.class);
            if (CollUtil.isEmpty(fl)) {
                throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
            }
            fl = fl.stream().filter(purchaseListEntity -> !ObjectSelfUtil.isAllFieldNull(purchaseListEntity)).collect(Collectors.toList());
            if (CollUtil.isEmpty(fl)) {
                throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
            }
            if (!fl.isEmpty()) {
                fl.stream().forEach(a -> {
                    TrainScore trainScore = new TrainScore();
                    BeanUtils.copyProperties(a, trainScore);
                    returnList.add(trainScore);
                });
            }
        } catch (IOException e) {
            throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
        }
        return returnList;
    }

    @Override
    public boolean finish(TrainExamFinishPo trainExamFinishPo) {
        IBeanUtil.paramVerify(trainExamFinishPo, "examCode");
        //查看是否登记完成
        if (trainExamFinishPo.getType() == 1) {
            return this.update(new UpdateWrapper<TrainExam>().set("STATUS", 2).eq("EXAM_CODE", trainExamFinishPo.getExamCode()));
        }
        if (trainExamFinishPo.getType() == 2) {
            int count = trainScoreService.count(new QueryWrapper<TrainScore>().eq("EXAM_CODE", trainExamFinishPo.getExamCode()).isNull("SCORE"));
            if (count <= 0) {//已经登记完成
                return true;
            } else {//还有未登记的
                return false;
            }
        }
        return false;
    }

    @Override
    public boolean downloadScoreTemp(TrainExam trainExam, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<>();
        String path = "\\templates\\tempOne.xls";
        TemplateExportParams templatePath = new TemplateExportParams(ConvertTemplatePath.convertTemplatePath(path));
        templatePath.setColForEach(true);

        List<TrainExamContent> contents = trainExamContentService
                .list(new QueryWrapper<TrainExamContent>().eq("EXAM_CODE", trainExam.getExamCode()));
        List<Map<String, Object>> list1 = new ArrayList<>();
        List<Map<String, Object>> list2 = new ArrayList<>();

        for (int i = 0; i < contents.size(); i++) {
            TrainExamContent content = contents.get(i);
            Map<String, Object> add = new HashMap<>();
            add.put("colName", content.getExamProject() + "评分");
//            add.put("colName1", content.getExamProject() + "得分");
            add.put("value1", "t.value1" + i);
//            add.put("value2", "t.value2" + i);
            list1.add(add);
        }
        List<TrainScore> scores = trainScoreService.getScoreByExamCode(trainExam.getExamCode());
        Set<String> userCodes = scores.stream().map(TrainScore::getUserCode).collect(Collectors.toSet());
        List<UserVos> userVos = this.getBaseMapper().userVos(userCodes);
        Map<String, UserVos> vosMap = userVos.stream().collect(Collectors.toMap(UserVos::getUserCode, Function.identity()));
        for (TrainScore score : scores) {
            Map<String, Object> add = new HashMap<>();
            String userCode = score.getUserCode();
            if (vosMap.containsKey(userCode)) {
                UserVos vos = vosMap.get(userCode);
                LocalDate now = LocalDate.now();
                LocalDate birthday = vos.getBirthday();
                int years = birthday.until(now).getYears();
                add.put("age", years);
                add.put("military", vos.getMilitaryRankName());
            }

            add.put("userName", score.getUserName());
            add.put("deptName", score.getPart());
            add.put("examName", score.getExamName());
            add.put("score", score.getScore());
            // 登记成绩
            List<TrainScoreContent> scoreList = trainScoreContentService
                    .list(new QueryWrapper<TrainScoreContent>().eq("SCORE_CODE", score.getScoreCode()));
            for (int i = 0; i < contents.size(); i++) {
                TrainExamContent content = contents.get(i);
                List<TrainScoreContent> collect = scoreList.stream()
                        .filter(t -> t.getExamProject().equals(content.getExamProject())).collect(Collectors.toList());
                if (collect.size() > 0) {
                    add.put("value1" + i, collect.get(0).getScore());
//                    add.put("value2" + i, collect.get(0).getScoRecord());
                }
            }
            list2.add(add);
        }
        map.put("cols", list1);
        map.put("userList", list2);
        try {
            ExcelUtils.exportExcel(templatePath, map, "成绩未导入列表", response);
        } catch (IOException e) {
            throw new BusinessException(ExceptionTrainEnum.TEMP_ERROR);
        }
        return true;
    }

    @Override
    public List<TrainExamScorePo> parseCopy(MultipartFile file) {
        List<TrainExamScorePo> returnList = new ArrayList<>();
        if (file.isEmpty()) {
            throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
        }
        List<Map<String, Object>> fl = new ArrayList<>();
        try {
            fl = ExcelUtils.importExcel(file, Map.class);
            if (CollUtil.isEmpty(fl)) {
                throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
            }
            fl = fl.stream().filter(purchaseListEntity -> !ObjectSelfUtil.isAllFieldNull(purchaseListEntity)).collect(Collectors.toList());
            if (CollUtil.isEmpty(fl)) {
                throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
            }
            if (fl.size() > 0) {
                fl.stream().forEach(a -> {
                    TrainExamScorePo trainScore = new TrainExamScorePo();
                    if (a.get("成绩") != null) {
                        trainScore.setScore(a.get("成绩").toString());
                    }
                    if (a.get("用户") != null) {
                        trainScore.setUserName(a.get("用户").toString());
                    }
                    if (a.get("所属单位") != null) {
                        trainScore.setPartName(a.get("所属单位").toString());
                    }
                    if (a.get("考核名称") != null) {
                        trainScore.setExamName(a.get("考核名称").toString());
                    }
                    List<Map<String, Object>> list = new LinkedList<>();
                    for (Map.Entry<String, Object> entry : a.entrySet()) {
                        if (!("成绩".equals(entry.getKey())) && (!"用户".equals(entry.getKey())) && !("所属单位".equals(entry.getKey())) && !("考核名称".equals(entry.getKey())) && !(entry.getKey().equals("excelRowNum"))) {
                            Map<String, Object> otherMap = new HashMap<>();
                            otherMap.put(entry.getKey(), entry.getValue());
                            list.add(otherMap);
                        }
                    }
                    if (CollUtil.isNotEmpty(list)) {
                        trainScore.setContentMap(list);
                    }
                    returnList.add(trainScore);
                });
            }
        } catch (IOException e) {
            throw new BusinessException(ExceptionTrainEnum.PARSE_ERROR);
        }
        return returnList;
    }

    @Override
    public List<ClassTreeVo> classTree(TrainExam trainExam) {
        List<ClassTreeVo> returnList = new LinkedList<>();
        IBeanUtil.paramVerify(trainExam, "examCode");
        TrainExam t = this.getOne(new QueryWrapper<TrainExam>().eq("EXAM_CODE", trainExam.getExamCode()));
        if (t == null) {
            return returnList;
        }
        Set<String> deptList = new HashSet<>();
        if (t.getResourceType() == 2) {
            String targetItem = t.getTargetItem();
            JSONArray deptArray = JSONObject.parseArray(targetItem);
            deptList.add("-1");
            if (deptArray != null && !deptArray.isEmpty()) {
                for (int i = 0; i < deptArray.size(); i++) {
                    deptList.add((String) deptArray.get(i));
                }
            }
        }

        List<DeptVo> deptByCodes = this.baseMapper.getDeptByCodes(deptList);
        if (deptByCodes == null) {
            return returnList;
        }
        deptByCodes.stream().forEach(a -> {
            if (!(deptByCodes.stream().anyMatch(s -> s.getDeptCode().equals(a.getParentDeptCode())))) {
                ClassTreeVo classTreeVo = new ClassTreeVo();
                classTreeVo.setDeptCode(a.getDeptCode());
                classTreeVo.setDeptName(a.getDeptName());
                returnList.add(classTreeVo);
            }
        });
        return diGuiClassTree(returnList, deptByCodes);
    }

    List<ClassTreeVo> diGuiClassTree(List<ClassTreeVo> list, List<DeptVo> allList) {
        list.stream().forEach(a -> {
            List<ClassTreeVo> classTreeVos = new LinkedList<>();
            allList.stream().forEach(b -> {
                if (a.getDeptCode().equals(b.getParentDeptCode())) {
                    ClassTreeVo classTreeVo = new ClassTreeVo();
                    classTreeVo.setDeptCode(b.getDeptCode());
                    classTreeVo.setDeptName(b.getDeptName());
                    classTreeVos.add(classTreeVo);
                }
            });
            a.setChildren(classTreeVos);
            if (classTreeVos != null && classTreeVos.size() > 0) {
                diGuiClassTree(classTreeVos, allList);
            }
        });
        return list;
    }

    @Override
    public Page<HashMap<String, String>> getTrainExam(GetTrainExamPo getTrainExamPo) {
        Page page = new Page(getTrainExamPo.getCurrent(), getTrainExamPo.getSize());
        return this.baseMapper.getTrainExam(page, getTrainExamPo);
    }

    @Override
    public HashMap<String, Object> statisticsExam(TrainScore trainScore) {
        IBeanUtil.paramVerify(trainScore, "examCode");
        HashMap<String, Object> hashMap = new HashMap<>();
        List<String> notList = new LinkedList<>();

        List<String> qualifiedList = new LinkedList<>();

        List<String> goodList = new LinkedList<>();

        List<String> outstandingList = new LinkedList<>();

        hashMap.put("item", this.baseMapper.getItemNumByExamCode(trainScore.getExamCode()));
        hashMap.put("participate", this.baseMapper.getExamNumByExamCode(trainScore.getExamCode()));
        Integer type=1;
        hashMap.put("qualified", this.baseMapper.getQualifiedNumByExamCode(trainScore.getExamCode(), qualifiedList,type));
        hashMap.put("good", this.baseMapper.getGoodNumByExamCode(trainScore.getExamCode(), goodList, type));
        hashMap.put("outstanding", this.baseMapper.getOutstandingNumByExamCode(trainScore.getExamCode(), outstandingList,type));
        return hashMap;
    }

    @Override
    public HashMap<String, Object> statisticsGrades(TrainScore trainScore) {
        IBeanUtil.paramVerify(trainScore, "examCode");
        HashMap<String, Object> hashMap = new HashMap<>();
        List<String> notList = new LinkedList<>();
        List<String> qualifiedList = new LinkedList<>();
        List<String> goodList = new LinkedList<>();
        List<String> outstandingList = new LinkedList<>();

        hashMap.put("notQualified", this.baseMapper.getNotQualifiedNumByExamCode(trainScore.getExamCode(), notList));
        Integer type=2;
        hashMap.put("qualified", this.baseMapper.getQualifiedNumByExamCode(trainScore.getExamCode(), qualifiedList,type));
        hashMap.put("good", this.baseMapper.getGoodNumByExamCode(trainScore.getExamCode(), goodList,type));
        hashMap.put("outstanding", this.baseMapper.getOutstandingNumByExamCode(trainScore.getExamCode(), outstandingList,type));
        return hashMap;
    }

    @Override
    public List<StatisticsGradesVo> statisticsConsume(StatisticsConsumePo statisticsConsumePo) {
        List<StatisticsGradesVo> statisticsGradesVos = this.baseMapper.statisticsConsume(statisticsConsumePo);
        List<String> dept = this.baseMapper.getDept();
        HashSet<String> deptCodes = new HashSet<>();
        if (dept != null && dept.size() > 0) {
            dept.stream().forEach(a -> {
                JSONArray jsonArray = JSONArray.parseArray(a);
                for (int i = 0; i < jsonArray.size(); i++) {
                    deptCodes.add(jsonArray.get(i).toString());
                }
            });
        }
        if (statisticsGradesVos != null && statisticsGradesVos.size() > 0) {
            statisticsGradesVos.stream().forEach(a -> {
                List<HashMap<String, Object>> hashMaps = new LinkedList<>();
                if (deptCodes != null && deptCodes.size() > 0) {
                    deptCodes.stream().forEach(b -> {
                        HashMap<String, Object> drugNum = this.baseMapper.getDrugNum(b, a.getDrugCode());
                        if (drugNum != null) {
                            hashMaps.add(drugNum);
                        }
                    });
                }
                a.setPartNum(hashMaps);
            });
        }
        return statisticsGradesVos;
    }

    @Override
    public List<StatisticsGradesVo> statisticsConsumeOfOil(StatisticsConsumePo statisticsConsumePo) {
        List<StatisticsGradesVo> statisticsGradesVos = this.baseMapper.statisticsConsumeOfOil(statisticsConsumePo);
        List<String> dept = this.baseMapper.getDept();
        HashSet<String> deptCodes = new HashSet<>();
        if (dept != null && dept.size() > 0) {
            dept.stream().forEach(a -> {
                JSONArray jsonArray = JSONArray.parseArray(a);
                for (int i = 0; i < jsonArray.size(); i++) {
                    deptCodes.add(jsonArray.get(i).toString());
                }
            });
        }
        if (statisticsGradesVos != null && statisticsGradesVos.size() > 0) {
            statisticsGradesVos.stream().forEach(a -> {
                List<HashMap<String, Object>> hashMaps = new LinkedList<>();
                if (deptCodes != null && deptCodes.size() > 0) {
                    deptCodes.stream().forEach(b -> {
                        HashMap<String, Object> drugNum = this.baseMapper.getDrugNum(b, a.getDrugCode());
                        if (drugNum != null) {
                            hashMaps.add(drugNum);
                        }
                    });
                }
                a.setPartNum(hashMaps);
            });
        }
        return statisticsGradesVos;
    }

    @Override
    public HashMap<String, Object> statisticsByCar() {
        HashMap<String, Object> returnMap = new HashMap<>();
        returnMap.put("class", this.baseMapper.classStatisticsByCar());
        returnMap.put("type", this.baseMapper.typeStatisticsByCar());
        return returnMap;
    }

    @Override
    public List<HashMap<String, Object>> statisticsByYear(StatisticsByYearPo statisticsByYearPo) {
        return this.baseMapper.statisticsByYear(statisticsByYearPo);
    }

    @Override
    @Transactional
    public List<TrainContentVo> contentImportExcel(MultipartFile file) {
        List<TrainContentVo> list = null;
        try {
            list = ExcelUtils.importExcel(file, TrainContentVo.class);
            list = list.stream().filter(i -> i.getExamProject() != null).collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<TrainContent> contents = new ArrayList<>();
        for (TrainContentVo trainContentVo : list) {
            TrainContent trainContent = BeanUtil.copyProperties(trainContentVo, TrainContent.class);
            UserCacheData user = ThreadUserContext.getCurrentCacheUser();
            trainContent.setCreateTime(LocalDateTime.now());
            trainContent.setCreatePersonCode(user.getUserCode());
            trainContent.setCreatePersonName(user.getUserName());
            trainContent.setBusinessCode(IdWorker.getIdStr());
            contents.add(trainContent);
        }
        if (CollUtil.isNotEmpty(contents)) {
            trainContentService.saveBatch(contents);
        }

        return list;
    }

    @Override
    public List<ContentInfoVo> contentList(ContentListPo contentListPo) {
        List<ContentInfoVo> contentInfoVo = new ArrayList<>();

        List<TrainExam> trainExams = this.list(Wrappers.<TrainExam>lambdaQuery()
                .eq(TrainExam::getStatus, 2));
        if (CollUtil.isNotEmpty(trainExams)) {
            List<String> examCodes = trainExams.stream().map(TrainExam::getExamCode).collect(Collectors.toList());
            if (contentListPo.getType() == 1) {
                IBeanUtil.paramVerify(contentListPo, "deptCode");
                List<TrainScore> trainScores = trainScoreService.list(Wrappers.<TrainScore>lambdaQuery()
                        .eq(TrainScore::getPart, contentListPo.getDeptCode())
                        .like(TrainScore::getCreateTime, contentListPo.getYear())
                        .in(TrainScore::getExamCode, examCodes));
                if (CollUtil.isNotEmpty(trainScores)) {
                    List<String> scoreCodes = trainScores.stream().map(TrainScore::getScoreCode).collect(Collectors.toList());
                    List<TrainScoreContent> trainScoreContents = trainScoreContentService.list(Wrappers.<TrainScoreContent>lambdaQuery()
                            .in(TrainScoreContent::getScoreCode, scoreCodes));
                    Set<String> contents = trainScoreContents.stream().map(TrainScoreContent::getExamProject).collect(Collectors.toSet());
                    Map<String, List<TrainScoreContent>> map = trainScoreContents.stream().collect(Collectors.groupingBy(TrainScoreContent::getExamProject));
                    for (String content : contents) {
                        ContentInfoVo infoVo = new ContentInfoVo();
                        infoVo.setName(content);
                        List<TrainScoreContent> contentList = map.get(content);
                        List<String> scores = contentList.stream().map(TrainScoreContent::getScore).filter(Objects::nonNull).collect(Collectors.toList());
                        List<Double> collect = scores.stream().map(Double::valueOf).collect(Collectors.toList());
                        double avg = collect.stream().collect(Collectors.averagingDouble(x -> x));
                        infoVo.setAvg(avg);
                        contentInfoVo.add(infoVo);
                    }
                }
            } else {
                IBeanUtil.paramVerify(contentListPo, "businessCode");
                TrainContent trainContentServiceOne = trainContentService.getOne(Wrappers.<TrainContent>lambdaQuery()
                        .eq(TrainContent::getBusinessCode, contentListPo.getBusinessCode()));
                String examProject = trainContentServiceOne.getExamProject();
                List<TrainScoreContent> trainScoreContents = trainScoreContentService.list(Wrappers.<TrainScoreContent>lambdaQuery()
                        .eq(TrainScoreContent::getExamProject, examProject)
                        .in(TrainScoreContent::getExamCode, examCodes));
                if (CollUtil.isNotEmpty(trainScoreContents)) {
                    Map<String, List<TrainScoreContent>> listMap = trainScoreContents.stream().collect(Collectors.groupingBy(TrainScoreContent::getScoreCode));
                    List<String> scoreCodes = trainScoreContents.stream().map(TrainScoreContent::getScoreCode).collect(Collectors.toList());
                    List<TrainScore> trainScores = trainScoreService.list(Wrappers.<TrainScore>lambdaQuery()
                            .in(TrainScore::getScoreCode, scoreCodes)
                            .like(TrainScore::getCreateTime, contentListPo.getYear()));
                    if (CollUtil.isNotEmpty(trainScores)) {
                        Map<String, List<TrainScore>> map = trainScores.stream().collect(Collectors.groupingBy(TrainScore::getPart));
                        Set<String> list = trainScores.stream().map(TrainScore::getPart).collect(Collectors.toSet());
                        List<DeptInfoVos> deptInfoVos = this.getBaseMapper().dept(list);
                        Map<String, DeptInfoVos> vosMap = deptInfoVos.stream().collect(Collectors.toMap(DeptInfoVos::getDeptCode, Function.identity()));
                        for (String s : list) {
                            ContentInfoVo infoVo = new ContentInfoVo();
                            infoVo.setCode(s);
                            infoVo.setName(vosMap.get(s).getDeptName());
                            List<TrainScore> scores = map.get(s);
                            List<Double> sums = new ArrayList<>();
                            for (TrainScore score : scores) {
                                if (listMap.containsKey(score.getScoreCode())) {
                                    List<TrainScoreContent> scoreContents = listMap.get(score.getScoreCode());
                                    List<String> collect = scoreContents.stream().map(TrainScoreContent::getScore).filter(Objects::nonNull).collect(Collectors.toList());
                                    List<Double> sum = collect.stream().map(Double::valueOf).collect(Collectors.toList());
                                    sums.addAll(sum);
                                }
                            }
                            if (CollUtil.isNotEmpty(sums)) {
                                double avg = sums.stream().collect(Collectors.averagingDouble(x -> x));
                                infoVo.setAvg(avg);
                            }
                            contentInfoVo.add(infoVo);
                        }
                    }
                }

            }
        }


        return contentInfoVo;
    }


}
